//
//  HJChatManager.m
//  KaiChat
//
//  Created by lx on 2023/10/20.
//

#import "HJChatManager.h"
#import "HJChatMessageModel.h"
#import "HJChatSessionModel.h"
#import "HJChatFriendModel.h"
#import "HJChatGroupModel.h"
#import "HJMessageTextDto.h"
#import "HJMessageImageDto.h"
#import "HJMessageVoiceDto.h"
#import "HJMessageVideoDto.h"
#import "HJMessageFileDto.h"
#import "HJIM.h"
#import "HJWebSocketManager.h"
#import "NSString+emoji.h"
#import "TUIDefine.h"
#import "EMVoiceConverter.h"
#import <AVFoundation/AVFoundation.h>
#import "TZImageManager.h"
#import "HJNetworkReachabilityManager.h"
#import "HJWebsiteFillter.h"
#import "HJAWSS3Manager.h"
#import "WAVideoBox.h"


@interface HJChatManager()

@property (nonatomic, strong) WAVideoBox *videoBox;

@end


@implementation HJChatManager

- (void)sendMessageWithModel:(HJChatMessageModel *)messageModel begin:(void (^__nullable)(void))begin completion:(void (^__nullable)(id  _Nullable response, NSError  * _Nullable error))completion {
    
    if (messageModel.asset) {
        [self sendMediaMessageWithModel:messageModel begin:begin completion:completion];
        return;
    }
    
    if (messageModel.messageType == HJMessageTypeText) {
        [self sendTextMessageWithModel:messageModel begin:begin completion:completion];
        return;
    }
    
    if (messageModel.messageType == HJMessageTypeImage) {
        [self sendImageMessageWithModel:messageModel begin:begin completion:completion];
        return;
    }
    
    if (messageModel.messageType == HJMessageTypeVoice) {
        [self sendVoiceMessageWithModel:messageModel begin:begin completion:completion];
        return;
    }
    
    if (messageModel.messageType == HJMessageTypeVideo) {
        [self sendVideoMessageWithModel:messageModel begin:begin completion:completion];
        return;
    }
    
}

- (void)sendTextMessageWithModel:(HJChatMessageModel *)messageModel begin:(void (^__nullable)(void))begin completion:(void (^__nullable)(id  _Nullable response, NSError  * _Nullable error))completion {
    
    NSLog(@"sendTextMessageWithModel = %@", messageModel);
    
    if (isEmptyString(messageModel.content)) return;
    
    dispatch_async_sql_queue(^{
        
        messageModel.messageType = HJMessageTypeText;
        [self setMessagePublicParameters:messageModel];
        BOOL isSuccess = [messageModel bg_saveOrUpdate];
        
        if (isSuccess) {
            HJChatSessionModel *sessionModel = [HJChatSessionModel sessionModelWithMessageModel:messageModel];
            [self setSessionModelInfo:sessionModel messageModel:messageModel];
            [[HJIM shareIM].conversationManager addConversation:sessionModel];
            messageModel.msgStatus = HJMessageStatusSending;
            [messageModel bg_saveOrUpdate];
            dispatch_async_main_queue(^{
                if (begin) {
                    begin();
                }
                [[NSNotificationCenter defaultCenter] postNotificationName:sendMessageStatusChangeNotification object:messageModel];
            });
            
            if (HJNetworkReachabilityManager.shareManager.networkReachabilityStatus == AFNetworkReachabilityStatusUnknown ||
                HJNetworkReachabilityManager.shareManager.networkReachabilityStatus == AFNetworkReachabilityStatusNotReachable
                ) {
                return;
            }
            
            HJMessageTextDto *messageDto = [HJMessageTextDto messageDtoWithMessageModel:messageModel];
            [self sendMessageWithModel:messageModel messageDto:messageDto completion:completion];
        }
    });
    
}

- (void)insertMessageWithModel:(HJChatMessageModel *)messageModel completion:(void (^__nullable)(void))completion {
    
    if (messageModel.messageType == HJMessageTypeSystem && isEmptyString(messageModel.content)) return;
    
    dispatch_async_sql_queue(^{
        [self setMessagePublicParameters:messageModel];
        BOOL isSuccess = [messageModel bg_saveOrUpdate];
        if (isSuccess) {
            HJChatSessionModel *sessionModel = [HJChatSessionModel sessionModelWithMessageModel:messageModel];
            [[HJIM shareIM].conversationManager addConversation:sessionModel];
            messageModel.msgStatus = HJMessageStatusSucceed;
            [messageModel bg_saveOrUpdate];
            dispatch_async_main_queue(^{
                if (completion) {
                    completion();
                }
            });
        }
    });
    
}

- (void)insertPayMessageWithModel:(HJChatMessageModel *)messageModel completion:(void (^__nullable)(void))completion {
    
    dispatch_async_sql_queue(^{
        
        messageModel.messageType = HJMessageTypeTransfer;
        [self setMessagePublicParameters:messageModel];
        BOOL isSuccess = [messageModel bg_saveOrUpdate];
        if (isSuccess) {
            HJChatSessionModel *sessionModel = [HJChatSessionModel sessionModelWithMessageModel:messageModel];
            [[HJIM shareIM].conversationManager addConversation:sessionModel];
            messageModel.msgStatus = HJMessageStatusSucceed;
            [messageModel bg_saveOrUpdate];
            dispatch_async_main_queue(^{
                if (completion) {
                    completion();
                } else {
                    [[NSNotificationCenter defaultCenter] postNotificationName:inserMessageNotification object:messageModel];
                }
            });
        }
    });
}

- (void)sendImageMessageWithModel:(HJChatMessageModel *)messageModel begin:(void (^__nullable)(void))begin completion:(void (^__nullable)(id  _Nullable response, NSError  * _Nullable error))completion {
    NSLog(@"%s", __func__);

    dispatch_async_sql_queue(^{
        
        BOOL isNewMessage = isEmptyString(messageModel.serverMsgId);
        
        messageModel.messageType = HJMessageTypeImage;
        [self setMessagePublicParameters:messageModel];
        
        BOOL isSuccess = [messageModel bg_saveOrUpdate];
        
        if (isSuccess) {
            
            if (isNewMessage) {
                HJChatSessionModel *sessionModel = [HJChatSessionModel sessionModelWithMessageModel:messageModel];
                [self setSessionModelInfo:sessionModel messageModel:messageModel];
                [[HJIM shareIM].conversationManager addConversation:sessionModel];
            }
            
            //先判断有没有缩略图地址
            NSString *thumbnailPath = messageModel.thumbnailPath;
            if (isEmptyString(thumbnailPath)) {
                thumbnailPath = [HJMessageFileManager imagefileFilePathWithSessionId:messageModel.sessionId fileName:getFileNameWithPathExtension(messageModel.localPath.pathExtension)];
            } else {
                thumbnailPath = [HJMessageFileManager imagefileFilePathWithSessionId:messageModel.sessionId fileName:messageModel.thumbnailPath.lastPathComponent];
            }
            
            //制作缩略图
            if (![[NSFileManager defaultManager] fileExistsAtPath:thumbnailPath]) {
                
                NSInteger maxByte = 50;
                NSData *thumbnailImageData = getThumbnailWithImage(messageModel.originalImage, CGSizeMake(TImageMessageCell_Image_Width_Max, TImageMessageCell_Image_Height_Max));
                if (thumbnailImageData.length > maxByte * 1024) {
                    thumbnailImageData = [UIImage compressWithImage:[UIImage imageWithData:thumbnailImageData] toByte:maxByte];
                }
                [HJTools writeImageData:thumbnailImageData toLocalPath:thumbnailPath];
                messageModel.thumbnailPath = thumbnailPath;
                messageModel.thumbnailImage = [UIImage imageWithData:thumbnailImageData];
            } else {
                messageModel.thumbnailImage = [UIImage imageWithContentsOfFile:thumbnailPath];
                messageModel.thumbnailPath = thumbnailPath;
            }
            
            //如果没有原图.直接回调失败
            if (![[NSFileManager defaultManager] fileExistsAtPath:messageModel.localPath]) {
                messageModel.msgStatus = HJMessageStatusFail;
                dispatch_async_main_queue(^{
                    if (begin) {
                        begin();
                    }
                });
                return;
            }
            
            messageModel.msgStatus = HJMessageStatusSending;
            [messageModel bg_saveOrUpdate];
            dispatch_async_main_queue(^{
                if (begin) {
                    begin();
                }
            });
            
            if (HJNetworkReachabilityManager.shareManager.networkReachabilityStatus == AFNetworkReachabilityStatusUnknown ||
                HJNetworkReachabilityManager.shareManager.networkReachabilityStatus == AFNetworkReachabilityStatusNotReachable
                ) {
                return;
            }
            
            [self getFileUrl:messageModel progress:^(CGFloat value) {
                messageModel.progress = value;
            } completion:^(NSError *error) {
                if (error) {
                    [self sendFailWithModel:messageModel error:error completion:completion];
                } else {
                    HJMessageImageDto *messageDto = [HJMessageImageDto messageDtoWithMessageModel:messageModel];
                    messageDto.originUrl = messageModel.fileUrl;
                    messageDto.content = messageModel.thumbnailUrl ?: messageModel.fileUrl;
                    [messageModel bg_saveOrUpdate];
                    [self sendMessageWithModel:messageModel messageDto:messageDto completion:completion];
                }
            }];
        }
    });
    
}

- (void)sendVoiceMessageWithModel:(HJChatMessageModel *)messageModel begin:(void (^__nullable)(void))begin completion:(void (^__nullable)(id  _Nullable response, NSError  * _Nullable error))completion {
    NSLog(@"%s", __func__);

    dispatch_async_sql_queue(^{
        
        BOOL isNewMessage = isEmptyString(messageModel.serverMsgId);
        
        messageModel.messageType = HJMessageTypeVoice;
        [self setMessagePublicParameters:messageModel];
        
        NSString *filePath = [HJMessageFileManager audiofileFilePathWithSessionId:messageModel.sessionId fileName:messageModel.localPath.lastPathComponent];
        [[NSFileManager defaultManager] moveItemAtPath:messageModel.localPath toPath:filePath error:nil];
        messageModel.localPath = filePath;
        
        BOOL isSuccess = [messageModel bg_saveOrUpdate];
        
        if (isNewMessage) {
            HJChatSessionModel *sessionModel = [HJChatSessionModel sessionModelWithMessageModel:messageModel];
            [self setSessionModelInfo:sessionModel messageModel:messageModel];
            [[HJIM shareIM].conversationManager addConversation:sessionModel];
        }
        
        if (isSuccess) {
            //语音的信息
            if (isEmptyString(messageModel.msg)) {
                NSURL *url = [NSURL fileURLWithPath:messageModel.localPath];
                AVURLAsset *audioAsset = [AVURLAsset URLAssetWithURL:url options:nil];
                long int duration = lroundf(CMTimeGetSeconds(audioAsset.duration));
                NSData *downloadData = [NSData dataWithContentsOfFile:messageModel.localPath];
                messageModel.msg = @{
                    @"fileSize": @(downloadData.length),
                    @"duration": @(duration).stringValue
                }.mj_JSONString;
            }
            
            messageModel.msgStatus = HJMessageStatusSending;
            [messageModel bg_saveOrUpdate];
            
            dispatch_async_main_queue(^{
                if (begin) {
                    begin();
                }
            });
            
            if (HJNetworkReachabilityManager.shareManager.networkReachabilityStatus == AFNetworkReachabilityStatusUnknown ||
                HJNetworkReachabilityManager.shareManager.networkReachabilityStatus == AFNetworkReachabilityStatusNotReachable
                ) {
                return;
            }
            
            [self getFileUrl:messageModel progress:^(CGFloat value) {
                messageModel.progress = value;
            } completion:^(NSError *error) {
                if (error) {
                    [self sendFailWithModel:messageModel error:error completion:completion];
                } else {
                    HJMessageVoiceDto *messageDto = [HJMessageVoiceDto messageDtoWithMessageModel:messageModel];
                    messageDto.content = messageModel.fileUrl;
                    [messageModel bg_saveOrUpdate];
                    [self sendMessageWithModel:messageModel messageDto:messageDto completion:completion];
                }
            }];
        }
    });
    
}

- (void)sendFileMessageWithModel:(HJChatMessageModel *)messageModel begin:(void (^__nullable)(void))begin completion:(void (^__nullable)(id  _Nullable response, NSError  * _Nullable error))completion {
    
}

- (void)sendVideoMessageWithModel:(HJChatMessageModel *)messageModel begin:(void (^__nullable)(void))begin completion:(void (^__nullable)(id  _Nullable response, NSError  * _Nullable error))completion {
    NSLog(@"%s", __func__);

    dispatch_async_sql_queue(^{
        
        BOOL isNewMessage = isEmptyString(messageModel.serverMsgId);
        
        messageModel.messageType = HJMessageTypeVideo;
        [self setMessagePublicParameters:messageModel];
        
        BOOL isSuccess = [messageModel bg_saveOrUpdate];
        
        if (isSuccess) {
            
            if (isNewMessage) {
                HJChatSessionModel *sessionModel = [HJChatSessionModel sessionModelWithMessageModel:messageModel];
                [self setSessionModelInfo:sessionModel messageModel:messageModel];
                [[HJIM shareIM].conversationManager addConversation:sessionModel];
            }
            
            //先判断有没有缩略图地址
            NSString *thumbnailPath = messageModel.thumbnailPath;
            if (isEmptyString(thumbnailPath)) {
                thumbnailPath = [HJMessageFileManager imagefileFilePathWithSessionId:messageModel.sessionId fileName:getFileNameWithPathExtension(messageModel.localPath.pathExtension)];
            } else {
                thumbnailPath = [HJMessageFileManager imagefileFilePathWithSessionId:messageModel.sessionId fileName:messageModel.thumbnailPath.lastPathComponent];
            }
            
            NSLog(@"保存到数据库成功 %@", messageModel);
            
            //制作缩略图
            if (![[NSFileManager defaultManager] fileExistsAtPath:thumbnailPath]) {
                UIImage *originImage = [HJTools getVideoFirstViewImageWithURL:[NSURL fileURLWithPath:messageModel.localPath]];
                CGSize thumbnailImageSize = getThumbnailImageSize(originImage.size, TImageMessageCell_Image_Width_Max);
                UIImage *thumbnailImage = [originImage imageSize:thumbnailImageSize color:UIColor.whiteColor];
                [HJTools writeImage:thumbnailImage toLocalPath:thumbnailPath];
                messageModel.thumbnailPath = thumbnailPath;
                messageModel.thumbnailImage = thumbnailImage;
            } else {
                messageModel.thumbnailImage = [UIImage imageWithContentsOfFile:thumbnailPath];
                messageModel.thumbnailPath = thumbnailPath;
            }
            
            if (isEmptyString(messageModel.msg)) {
                NSURL *url = [NSURL fileURLWithPath:messageModel.localPath];
                AVURLAsset *asset = [AVURLAsset URLAssetWithURL:url options:nil];
                long int duration = lroundf(CMTimeGetSeconds(asset.duration));
                NSData *downloadData = [NSData dataWithContentsOfFile:messageModel.localPath];
                messageModel.msg = @{
                    @"fileSize": @(downloadData.length),
                    @"duration": @(duration).stringValue
                }.mj_JSONString;
            }
            
            //如果没有原图.直接回调失败
            
            NSLog(@"messageModel = %@, %@", messageModel, messageModel.localPath.lastPathComponent);
            if (messageModel.localPath) {
                messageModel.localPath = [HJMessageFileManager videofileFilePathWithSessionId:messageModel.sessionId fileName:messageModel.localPath.lastPathComponent];
                NSLog(@"messageModel.localPath = %@", messageModel.localPath);
            }
            
            if (![[NSFileManager defaultManager] fileExistsAtPath:messageModel.localPath]) {
                NSLog(@"不存在本地路径发送失败");
                //重新获取
                    if (messageModel.localIdentifier.length) {
                        PHFetchResult *fetchResult = [PHAsset fetchAssetsWithLocalIdentifiers:@[messageModel.localIdentifier] options:nil];
                        messageModel.asset = fetchResult.firstObject;
                        [self sendMediaMessageWithModel:messageModel begin:begin completion:completion];
                    } else {
                        messageModel.msgStatus = HJMessageStatusFail;
                        dispatch_async_main_queue(^{
                            if (begin) {
                                begin();
                            }
                        });
                    }
                return;
            }
            
            NSLog(@"正在发送");
            messageModel.msgStatus = HJMessageStatusSending;
            [messageModel bg_saveOrUpdate];
            dispatch_async_main_queue(^{
                if (begin) {
                    begin();
                }
            });
            
            if (HJNetworkReachabilityManager.shareManager.networkReachabilityStatus == AFNetworkReachabilityStatusUnknown ||
                HJNetworkReachabilityManager.shareManager.networkReachabilityStatus == AFNetworkReachabilityStatusNotReachable
                ) {
                NSLog(@"判断没网络");
                return;
            }
            
//            /var/mobile/Containers/Data/Application/ACC79D63-2236-438B-A620-6BF357222A7B/Library/Caches/Message/534228390232197/143/Video/9e68858019236d3b367cc158b2b60ad7.mov
            //压缩
            NSString *tempLocalPath = [HJMessageFileManager videofileFilePathWithSessionId:messageModel.sessionId fileName:getFileNameWithPathExtension(messageModel.localPath.pathExtension)];
            NSString *sourcePath = messageModel.localPath;
            [self compressVideoWithSourcePath:sourcePath localPath:tempLocalPath messageType:messageModel.messageType completion:^(NSError *compressError) {
                if (!compressError) {//替换路径
                    NSLog(@"压缩成功替换路径 %@", tempLocalPath);
                    messageModel.localPath = tempLocalPath;
                    NSData *downloadData = [NSData dataWithContentsOfFile:messageModel.localPath];
                    NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithDictionary:[messageModel.msg mj_JSONObject]];
                    [dict setValue:@(downloadData.length) forKey:@"fileSize"];
                    messageModel.msg = dict.mj_JSONString;
                    if ([[NSFileManager defaultManager] fileExistsAtPath:tempLocalPath] && [[NSFileManager defaultManager] fileExistsAtPath:sourcePath]) {
                        [[NSFileManager defaultManager] removeItemAtPath:sourcePath error:nil];
                    }
                    [messageModel bg_saveOrUpdateAsync:nil];
                }
                
                [self getThumbnailImageUrl:messageModel completion:^(NSError * _Nullable thumbnailError) {
                    if (thumbnailError) { //回调错误
                        [self sendFailWithModel:messageModel error:thumbnailError completion:completion];
                    } else {
                        [self getFileUrl:messageModel progress:^(CGFloat value) {
                            messageModel.progress = value;
                        } completion:^(NSError *error) {
                            if (error) {
                                [self sendFailWithModel:messageModel error:error completion:completion];
                            } else {
                                HJMessageVideoDto *messageDto = [HJMessageVideoDto messageDtoWithMessageModel:messageModel];
                                messageDto.content = messageModel.fileUrl;
                                messageDto.originUrl = messageModel.thumbnailUrl;
                                [messageModel bg_saveOrUpdate];
                                [self sendMessageWithModel:messageModel messageDto:messageDto completion:completion];
                            }
                        }];
                    }
                }];
            }];
        }
    });
}

- (void)getLocalPathWithMessageModel:(HJChatMessageModel *)messageModel completion:(void (^__nullable)(void))completion {
    
    
}

- (void)sendMessageWithModel:(HJChatMessageModel *)messageModel messageDto:(HJMessageDto *)messageDto completion:(void (^__nullable)(id  _Nullable response, NSError  * _Nullable error))completion {
    if ([messageModel.receiverId isEqualToString:messageModel.senderId]) {
        [self sendSucceedWithModel:messageModel completion:completion];
        return;
    }
    NSLog(@"开始发送消息");
    [HJWebSocketManager.shareManager sendMessageWithDto:messageDto complete:^(NSDictionary * _Nullable data, NSError * _Nullable error) {
        if (!error) {
            messageModel.serverMsgId = toString(data[@"seq_id"]);
            [self sendSucceedWithModel:messageModel completion:completion];
        } else {
            [self sendFailWithModel:messageModel error:error completion:completion];
        }
    }];
}

- (void)sendFailWithModel:(HJChatMessageModel *)messageModel error:(NSError *)error completion:(void (^__nullable)(id  _Nullable response, NSError  * _Nullable error))completion{
    messageModel.msgStatus = HJMessageStatusFail;
    
    [messageModel bg_saveOrUpdateAsync:^(BOOL __isSuccess) {
        dispatch_async_main_queue(^{
            if (completion) {
                completion(nil, error);
            }
            [[NSNotificationCenter defaultCenter] postNotificationName:sendMessageCompleteNotification object:messageModel];
        });
        
        if ([error.domain isEqualToString:ERRPRDOMAIN]) {
            
            
            if (error.code == 1501 || error.code == 1504) {
                
                HJChatMessageModel *systemMessageModel = [[HJChatMessageModel alloc] init];
                systemMessageModel.chatType = HJChatTypeSingle;
                systemMessageModel.messageType = HJMessageTypeSystem;
                systemMessageModel.sessionId = messageModel.sessionId;
                systemMessageModel.receiverId = messageModel.receiverId;
                systemMessageModel.msgId = getMessageId();
                
                if (error.code == 1501) {
                    messageModel.isBlacklisted = YES;
                    systemMessageModel.content = blacklistedTip;
                } else {
                    systemMessageModel.content = error.localizedFailureReason;
                    systemMessageModel.msgId = getMessageId();
                }
                
                messageModel.bindingTipMsgId = systemMessageModel.msgId;
                [messageModel bg_saveOrUpdateAsync:nil];
                
                [HJIM.shareIM.chatManager insertMessageWithModel:systemMessageModel completion:^{
                    [[NSNotificationCenter defaultCenter] postNotificationName:inserMessageNotification object:systemMessageModel];
                }];
            }
        }
    }];
}

- (void)sendSucceedWithModel:(HJChatMessageModel *)messageModel completion:(void (^__nullable)(id  _Nullable response, NSError  * _Nullable error))completion {
    messageModel.msgStatus = HJMessageStatusSucceed;
    messageModel.isBlacklisted = NO;
    [messageModel bg_saveOrUpdateAsync:^(BOOL __isSuccess) {
        [messageModel previewLink];
        dispatch_async_main_queue(^{
            if (completion) {
                completion(messageModel, nil);
            }
            [[NSNotificationCenter defaultCenter] postNotificationName:sendMessageCompleteNotification object:messageModel];
        });
    }];
}

- (void)setMessagePublicParameters:(HJChatMessageModel *)messageModel {
    messageModel.unReadCount = @"0";
    
    if (messageModel.chatType == HJChatTypeGroup) {
        HJChatGroupModel *groupModel = [HJIM.shareIM.groupManager queryGroupInfoByGroupId:toString(messageModel.groupId ?: messageModel.sessionId)];
        messageModel.sessionName = groupModel.name;
        messageModel.sessionAvatar = groupModel.avatar;
        messageModel.sessionId = groupModel.groupId;
        messageModel.groupId = groupModel.groupId;
        messageModel.groupName = groupModel.name;
    }  else {
        
        HJChatFriendModel *friendModel = [HJIM.shareIM.userManager queryFriendInfoByFriendId:toString(messageModel.receiverId)];
        messageModel.receiverNickname = friendModel.showName;
        messageModel.receiverAvatar = friendModel.avatar;
        messageModel.sessionName = messageModel.receiverNickname;
        messageModel.sessionAvatar = messageModel.receiverAvatar;
    }
    
    messageModel.msgStatus = HJMessageStatusNone;
    messageModel.senderId = HJUserInfo.userId;
    messageModel.senderAvatar = HJUserInfo.avatar;
    messageModel.senderNickname = HJUserInfo.nickname;
    
    if (messageModel.isForword) {
        messageModel.msgId = getMessageId();
        messageModel.timestamp = [NSString stringWithFormat:@"%.f", [[NSDate date] timeIntervalSince1970] * 1000];
    } else {
        
        if (messageModel.msgId) {
            messageModel.isRetry = YES;
        } else {
            messageModel.msgId = getMessageId();
        }
        
        messageModel.sequenceMsgId = messageModel.sequenceMsgId ?: [NSNumber numberWithUnsignedLongLong:getSequenceId()];
        messageModel.timestamp = messageModel.timestamp ?: [NSString stringWithFormat:@"%.f", [[NSDate date] timeIntervalSince1970] * 1000];
        if (messageModel.isRetry) {
            messageModel.timestamp = [NSString stringWithFormat:@"%.f", [[NSDate date] timeIntervalSince1970] * 1000];
        }
    }
}

- (void)setSessionModelInfo:(HJChatSessionModel *)sessionModel messageModel:(HJChatMessageModel *)messageModel {
    sessionModel.isSendMsg = @"1";
    
    BOOL isNewSession = [HJIM.shareIM.conversationManager getConversationBySessionId:sessionModel.sessionId] == nil;
    if (isNewSession) {
        [HJIM.shareIM.conversationManager loadConversatioInfoWithSessionId:sessionModel.sessionId type:sessionModel.chatType completion:^(HJChatSessionModel * _Nonnull loadSessionModel) {
            sessionModel.isTop = loadSessionModel.isTop;
            sessionModel.isMute = loadSessionModel.isMute;
            [sessionModel bg_saveOrUpdateAsync:^(BOOL isSuccess) {
                dispatch_async_main_queue(^{
                    [[NSNotificationCenter defaultCenter] postNotificationName:updateConversationInfoNotification object:sessionModel];
                });
            }];
        }];
    }
}

- (void)getOriginalImageWithMessageWithModel:(HJChatMessageModel *)messageModel completion:(void (^__nullable)(UIImage *  _Nullable image))completion {
    
    if (messageModel.originalImage && messageModel.originalImage.size.width > 0 && messageModel.originalImage.size.height > 0) {
        completion(messageModel.originalImage);
        return;
    }
    
    PHAsset *asset = messageModel.asset;
    if (!asset) {
        if (messageModel.localIdentifier.length) {
            PHFetchResult *fetchResult = [PHAsset fetchAssetsWithLocalIdentifiers:@[messageModel.localIdentifier] options:nil];
            messageModel.asset = fetchResult.firstObject;;
        }
    }
//    /var/mobile/Containers/Data/Application/9314E747-885E-417B-A44E-D7B3FF15C373/Library/Caches/Message/534228390232197/143/Video/79d56ce49176aae8662167679caeb42d.mov
    if (messageModel.asset.mediaType == PHAssetMediaTypeImage) {
        [[TZImageManager manager] requestImageDataForAsset:asset completion:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
            
            NSString *imageType = nil;
            if ([info objectForKey:@"PHImageFileUTIKey"]) {
                imageType = info[@"PHImageFileUTIKey"];
            }
            
            completion([UIImage imageWithData:imageData]);
        } progressHandler:nil];
    }
}

- (void)sendMediaMessageWithModel:(HJChatMessageModel *)messageModel begin:(void (^__nullable)(void))begin completion:(void (^__nullable)(id  _Nullable response, NSError  * _Nullable error))completion  {
    
    NSLog(@"%s", __func__);
    
    //断网的时候发送中的逻辑

    PHAsset *asset = messageModel.asset;
    
    if (messageModel.asset.mediaType == PHAssetMediaTypeImage) {
        
        if ([[NSFileManager defaultManager] fileExistsAtPath:messageModel.localPath]) {
            NSLog(@"存在图片本地路径");
            [self sendImageMessageWithModel:messageModel begin:begin completion:completion];
            return;
        }
        
        dispatch_async_global_queue(^{
            
            PHAssetResource *assetResource = [[PHAssetResource assetResourcesForAsset:asset] firstObject];
            NSString *fileName = assetResource.originalFilename;
            if (!fileName) {
                fileName = [asset valueForKey:@"filename"];
            }
            
            fileName = getFileNameWithPathExtension(fileName ? fileName.pathExtension : @"jpg");
            NSString *localPath = [HJMessageFileManager imagefileFilePathWithSessionId:messageModel.sessionId fileName:fileName];
            messageModel.localIdentifier = messageModel.asset.localIdentifier;
            
            [self getOriginalImageWithMessageWithModel:messageModel completion:^(UIImage * _Nullable image) {
                [HJTools writeImage:image toLocalPath:localPath];
                messageModel.localPath = localPath;
                [self sendImageMessageWithModel:messageModel begin:begin completion:completion];
            }];
        });
        return;
    }
    
    if (messageModel.asset.mediaType == PHAssetMediaTypeVideo) {
        
        if ([[NSFileManager defaultManager] fileExistsAtPath:messageModel.localPath]) {
            NSLog(@"存在视频本地路径");
            [self sendVideoMessageWithModel:messageModel begin:begin completion:completion];
            return;
        }
        
        [[TZImageManager manager] requestVideoURLWithAsset:messageModel.asset success:^(NSURL *videoURL) {
            
            messageModel.localIdentifier = messageModel.asset.localIdentifier;

            dispatch_async_global_queue(^{
                
                NSString *fileName = getFileNameWithPathExtension(videoURL.pathExtension);
                NSString *filePath = [HJMessageFileManager videofileFilePathWithSessionId:messageModel.sessionId fileName:fileName];
                
                if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
                    [[NSFileManager defaultManager] removeItemAtPath:filePath error:nil];
                }
                
                NSError *error = nil;
                [[NSFileManager defaultManager] copyItemAtURL:videoURL toURL:[NSURL fileURLWithPath:filePath] error:&error];
                if (error) {
                    completion(nil, error);
                    return;
                }
//                TJLog(@"videoPath = %@, size = %lld", filePath, getFileSizeAtPath(filePath));
                messageModel.localPath = filePath;
                [self sendVideoMessageWithModel:messageModel begin:begin completion:completion];
            });
        } failure:^(NSDictionary *info) {
            completion(nil, [NSError errorWithCode:1000 errorReason:@"获取视频URL失败"]);
        }];
        return;
    }
    
}


//如果是视频的话先压缩

- (WAVideoBox *)videoBox {
    if (!_videoBox) {
        _videoBox = [[WAVideoBox alloc] init];
    }
    return _videoBox;
}

- (void)compressVideoWithSourcePath:(NSString *)sourcePath localPath:(NSString *)localPath messageType:(HJMessageType)messageType completion:(void(^)( NSError *compressError))completion {
    NSLog(@"开始压缩");
    [self.videoBox appendVideoByPath:sourcePath];
    long long oldSize = getFileSizeAtPath(sourcePath);
    NSLog(@"压缩前size %lld", getFileSizeAtPath(sourcePath));
    self.videoBox.ratio = WAVideoExportRatioHighQuality;
    self.videoBox.videoQuality = 10;
    [self.videoBox asyncFinishEditByFilePath:localPath complete:^(NSError *error) {
        long long size = getFileSizeAtPath(localPath);
        NSLog(@"压缩后%lld ----> 减少 = %.2f%%", size, (oldSize - size) / (oldSize * 1.0) * 100);
        if (oldSize < size) {
            completion([NSError errorWithCode:-10001 errorReason:@"压缩失败"]);
            return;
        }
        completion(error);
    }];
}

- (void)getThumbnailImageUrl:(HJChatMessageModel *)messageModel completion:(void(^)(NSError * _Nullable thumbnailError))completion {
    
    if (messageModel.thumbnailUrl) {
        completion(nil);
        return;
    }
    
    NSLog(@"上传缩略图");
    NSString *thumbnailObjectKey = getUploadFileKey(HJFileTypeImage, [NSString stringWithFormat:@"%@.%@", [NSString stringWithFormat:@"%.f", NSDate.date.timeIntervalSince1970 * 1000].md5, @"jpg"]);
    NSData *thumbnailData = [NSData dataWithContentsOfFile:messageModel.thumbnailPath];
    [HJAWSS3Manager.shareS3Manager updateWithData:thumbnailData objectKey:thumbnailObjectKey progressBlock:^(int64_t totalBytesSent, int64_t completeBytes) {
//                    dispatch_async_main_queue(^{
//                        [[NSNotificationCenter defaultCenter] postNotificationName:updateChatFileUploadProgressNotification object:@{
//                            @"msgId": messageModel.msgId,
//                            @"progress": @(completeBytes / ((totalBytesSent) * 1.0))
//                        }];
//                    });
    } completionHandler:^(NSString * _Nullable url, NSError * _Nullable error) {

        if (error) { //回调错误
            !completion ?: completion(error);
        } else {
            messageModel.thumbnailUrl = url;
            !completion ?: completion(nil);
        }
    }];
}


- (void)getFileUrl:(HJChatMessageModel *)messageModel progress:(void (^)(CGFloat value))progress completion:(void(^)(NSError * _Nullable error))completion {
    
    if (messageModel.isForword && !isEmptyString(messageModel.fileUrl)) {
        progress(1);
        completion(nil);
        return;
    }
    
    
    NSLog(@"上传文件localPath = %@", messageModel.localPath);
    
    HJFileType fileType = HJFileTypeOther;
    if (messageModel.messageType == HJMessageTypeImage) {
        fileType = HJFileTypeImage;
    } else if (messageModel.messageType == HJMessageTypeVoice) {
        fileType = HJFileTypeVoice;
    } else if (messageModel.messageType == HJMessageTypeVideo) {
        fileType = HJFileTypeVideo;
    } else if (messageModel.messageType == HJMessageTypeOther) {
        fileType = HJFileTypeOther;
    }
    
    
    if (isEmptyString(messageModel.fileUrl)) {
        
        if (messageModel.messageType == HJMessageTypeVoice) {
            
            messageModel.localPath = [HJMessageFileManager audiofileFilePathWithSessionId:messageModel.sessionId fileName:messageModel.localPath.lastPathComponent];
            
            NSString *uploadPath = getFileNameWithPathExtension(messageModel.localPath.pathExtension);
            NSString *amrUploadPath = [[uploadPath stringByDeletingPathExtension] stringByAppendingString:@".amr"];
            NSString *armLocalPath = [HJMessageFileManager audiofileFilePathWithSessionId:messageModel.sessionId fileName:amrUploadPath.lastPathComponent];
            uploadPath = amrUploadPath;
            
            NSLog(@"uploadPath = %@", uploadPath);
            
            int result = [EMVoiceConverter wavToAmr:messageModel.localPath amrSavePath:armLocalPath];
            
            if (result == 0) {
                AVURLAsset *audioAsset = [AVURLAsset URLAssetWithURL:[NSURL fileURLWithPath:armLocalPath] options:nil];
                NSInteger calculateDuration = lroundf(CMTimeGetSeconds(audioAsset.duration));
                NSInteger duration = MIN(60, calculateDuration);
                
                messageModel.msg = @{
                    @"fileSize": @(getFileSizeAtPath(armLocalPath)),
                    @"duration": @(duration).stringValue
                }.mj_JSONString;
                [messageModel bg_saveOrUpdate];
                
                NSString *objectKey = getUploadFileKey(fileType, [NSString stringWithFormat:@"%@.%@", [NSString stringWithFormat:@"%.f", NSDate.date.timeIntervalSince1970 * 1000].md5, uploadPath.pathExtension]);
                NSData *fileData = [NSData dataWithContentsOfFile:messageModel.localPath];
                [HJNetworking.shareNetwork uploadImageWithObejctKey:objectKey fileData:fileData progress:nil success:^(NSString * _Nonnull url){
                    messageModel.fileUrl = url;
                    if ([[NSFileManager defaultManager] fileExistsAtPath:armLocalPath]) {
                        [[NSFileManager defaultManager] removeItemAtPath:armLocalPath error:nil];
                    }
                    completion(nil);
                } failure:^(NSError * _Nonnull error) {
                    messageModel.fileUrl = @"";
                    completion(error);
                }];
            } else {
                completion([NSError errorWithCode:-10001 errorReason:@"音频转换失败"]);
            }
            return;
        }
        
        NSData *fileData = nil;
        
        if (messageModel.messageType == HJMessageTypeImage) {
            if (messageModel.originalImage) {
                fileData = UIImageJPEGRepresentation(messageModel.originalImage, 0.6);
            } else {
                fileData = [NSData dataWithContentsOfFile:messageModel.localPath];
            }
        } else {
            fileData = [NSData dataWithContentsOfFile:messageModel.localPath];
        }
        
        NSString *objectKey = getUploadFileKey(fileType, [NSString stringWithFormat:@"%@.%@", [NSString stringWithFormat:@"%.f", NSDate.date.timeIntervalSince1970 * 1000].md5, messageModel.localPath.pathExtension]);
        
        [HJAWSS3Manager.shareS3Manager updateWithData:fileData objectKey:objectKey progressBlock:^(int64_t totalBytesSent, int64_t completeBytes) {
            dispatch_async_main_queue(^{
                [[NSNotificationCenter defaultCenter] postNotificationName:updateChatFileUploadProgressNotification object:@{
                    @"msgId": messageModel.msgId,
                    @"progress": @(completeBytes / ((totalBytesSent) * 1.0))
                }];
            });
        } completionHandler:^(NSString * _Nullable url, NSError * _Nullable error) {
            if (!error) {
                messageModel.fileUrl = url;
                if (messageModel.messageType == HJMessageTypeImage) {
                    messageModel.thumbnailUrl = messageModel.fileUrl;
                }
                completion(nil);
            } else {
                messageModel.fileUrl = nil;
                completion(error);
            }
        }];
    } else {
        progress(1);
        completion(nil);
    }
    
}

- (void)getFirstLoginReplyMessageCompletion:(void (^__nullable)(HJChatMessageModel  * _Nullable replyMessageModel, NSError  * _Nullable error))completion {
    [self getAutoReplyMessageWithType:1 completion:completion];
}

- (void)getFAQMessageCompletion:(void (^__nullable)(HJChatMessageModel  * _Nullable replyMessageModel, NSError  * _Nullable error))completion {
    [self getAutoReplyMessageWithType:2 completion:completion];
}

- (void)getAutoReplyMessageWithType:(NSInteger)type completion:(void (^__nullable)(HJChatMessageModel  * _Nullable replyMessageModel, NSError  * _Nullable error))completion {
    [HJNetworking.shareNetwork POSTBodyJSON:API_autoReply parameters:@{
        @"message_type": @(type)
    } success:^(NSDictionary * _Nonnull responseObject, id  _Nonnull data) {
        
        if (isEmptyString(data[@"content"])) {
            return;
        };
        
        dispatch_async_sql_queue(^{
            HJChatMessageModel *messageModel = [[HJChatMessageModel alloc] init];
            messageModel.chatType = HJChatTypeOfficial;
            messageModel.officialType = HJChatOfficialTypeKaiSupport;
            messageModel.messageType = HJMessageTypeAutoReply;
            
            messageModel.senderId = toString(data[@"session_id"]);
            messageModel.senderNickname = data[@"name"];
            messageModel.senderAvatar = data[@"image"];
            
            messageModel.receiverId = HJUserInfo.userId;
            messageModel.receiverAvatar = HJUserInfo.avatar;
            messageModel.receiverNickname = HJUserInfo.nickname;
            
            messageModel.content = data[@"content"];
            messageModel.msg = @"Welcome to kai chats";
            messageModel.sessionId = getOfficiaSessionId(data[@"session_id"]);
            messageModel.timestamp = [NSString stringWithFormat:@"%.f", [[NSDate date] timeIntervalSince1970] * 1000];
            messageModel.msgId = getMessageId();
            messageModel.msgStatus = HJMessageStatusSucceed;
            
            BOOL isSuccess = [messageModel bg_saveOrUpdate];
            
            if (isSuccess) {
                HJChatSessionModel *sessionModel = [HJChatSessionModel sessionModelWithMessageModel:messageModel];
                sessionModel.isTop = toString(data[@"is_top"]);
                sessionModel.isMute = toString(data[@"is_mute"]);
                sessionModel.sessionName = messageModel.senderNickname;
                sessionModel.sessionAvatar = messageModel.senderAvatar;
                if (type == 1) {
                    sessionModel.unReadCount = @"1";
                }
                
                HJChatSessionModel *lastSessionModel = [HJIM.shareIM.conversationManager getConversationBySessionId:sessionModel.sessionId];
                sessionModel.unReadCount = toString(@(lastSessionModel.unReadCount.integerValue + sessionModel.unReadCount.integerValue));
                [sessionModel bg_saveOrUpdate];
                [[NSNotificationCenter defaultCenter] postNotificationName:updateConversationNotification object:sessionModel];
                
                dispatch_async_main_queue(^{
                    [[NSNotificationCenter defaultCenter] postNotificationName:receiveNewMessageNotification object:messageModel];
                    if (completion) {
                        completion(messageModel, nil);
                    }
                });
            }
        });
    } failure:^(NSError * _Nonnull error) {
        
    }];
}


- (void)sendKeywordReplyMessageWithModel:(HJChatMessageModel *)messageModel begin:(void (^__nullable)(void))begin completion:(void (^__nullable)(HJChatMessageModel  * _Nullable replyMessageModel, NSError  * _Nullable error))completion {
    
    if (isEmptyString(messageModel.content)) return;
    
    dispatch_async_sql_queue(^{
        
        messageModel.chatType = HJChatTypeOfficial;
        messageModel.messageType = HJMessageTypeText;
        messageModel.officialType = HJChatOfficialTypeKaiSupport;
        messageModel.msgStatus = HJMessageStatusNone;
        messageModel.senderId = HJUserInfo.userId;
        messageModel.senderAvatar = HJUserInfo.avatar;
        messageModel.senderNickname = HJUserInfo.nickname;
        messageModel.msgId = getMessageId();
        messageModel.timestamp = [NSString stringWithFormat:@"%.f", [[NSDate date] timeIntervalSince1970] * 1000];
        
        BOOL isSuccess = [messageModel bg_saveOrUpdate];
        
        if (isSuccess) {
            HJChatSessionModel *sessionModel = [HJChatSessionModel sessionModelWithMessageModel:messageModel];
            [self setSessionModelInfo:sessionModel messageModel:messageModel];
            [[HJIM shareIM].conversationManager addConversation:sessionModel];
            messageModel.msgStatus = HJMessageStatusSending;
            [messageModel bg_saveOrUpdate];
            dispatch_async_main_queue(^{
                if (begin) {
                    begin();
                }
                [[NSNotificationCenter defaultCenter] postNotificationName:sendMessageStatusChangeNotification object:messageModel];
            });
            
            if (HJNetworkReachabilityManager.shareManager.networkReachabilityStatus == AFNetworkReachabilityStatusUnknown ||
                HJNetworkReachabilityManager.shareManager.networkReachabilityStatus == AFNetworkReachabilityStatusNotReachable
                ) {
                return;
            }
            
            [HJNetworking.shareNetwork POSTBodyJSON:API_keywordReply parameters:@{
                @"keyword": messageModel.content
            } success:^(NSDictionary * _Nonnull responseObject, id  _Nonnull data) {
                
                dispatch_async_sql_queue(^{
                    
                    messageModel.msgStatus = HJMessageStatusSucceed;
                    [messageModel bg_saveOrUpdate];
                    dispatch_async_main_queue(^{
                        [[NSNotificationCenter defaultCenter] postNotificationName:sendMessageCompleteNotification object:messageModel];
                    });
                    
                    if (isEmptyString(data[@"desc"])) return;
                    
                    HJChatMessageModel *replyMessageModel = [[HJChatMessageModel alloc] init];
                    
                    replyMessageModel.chatType = HJChatTypeOfficial;
                    replyMessageModel.officialType = HJChatOfficialTypeKaiSupport;
                    replyMessageModel.messageType = HJMessageTypeKeyboardReply;
                    
                    replyMessageModel.senderId = toString(data[@"session_id"]);
                    replyMessageModel.senderNickname = data[@"name"];
                    replyMessageModel.senderAvatar = data[@"image"];
                    
                    replyMessageModel.receiverId = HJUserInfo.userId;
                    replyMessageModel.receiverAvatar = HJUserInfo.avatar;
                    replyMessageModel.receiverNickname = HJUserInfo.nickname;
                    
                    replyMessageModel.content = data[@"content"];
                    replyMessageModel.msg = [data mj_JSONString];
                    replyMessageModel.sessionId = getOfficiaSessionId(data[@"session_id"]);
                    replyMessageModel.timestamp = [NSString stringWithFormat:@"%.f", [[NSDate date] timeIntervalSince1970] * 1000];
                    replyMessageModel.msgId = getMessageId();
                    replyMessageModel.msgStatus = HJMessageStatusSucceed;
                    
                    BOOL isSuccess = [replyMessageModel bg_saveOrUpdate];
                    
                    if (isSuccess) {
                        HJChatSessionModel *sessionModel = [HJChatSessionModel sessionModelWithMessageModel:messageModel];
                        [[HJIM shareIM].conversationManager addConversation:sessionModel];
                        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(500 * NSEC_PER_MSEC)), dispatch_get_main_queue(), ^{
                            [[NSNotificationCenter defaultCenter] postNotificationName:receiveNewMessageNotification object:replyMessageModel];
                            if (completion) {
                                completion(replyMessageModel, nil);
                            }
                        });
                    }
                });
            } failure:^(NSError * _Nonnull error) {
                
            }];
            
        }
    });
    
    
}

- (void)queryOfficialAccountCompletion:(void (^__nullable)(NSArray  * _Nullable datas))completion {
    
    NSArray *list = [NSUserDefaults.standardUserDefaults valueForKey:@"officialList"];
    NSMutableArray *sessionModels = [self transitionToSessionModels:list];
    completion(sessionModels);
    
    if (sessionModels.count == 0) {
        [HJNetworking.shareNetwork GET:API_officialList parameters:nil success:^(NSDictionary * _Nonnull responseObject, id  _Nonnull data) {
            
            NSArray *list = data[@"list"];
            NSMutableArray *sessionModels = [self transitionToSessionModels:list];
            if (completion) {
                completion(sessionModels);
            }
            
            dispatch_async_sql_queue(^{
                [NSUserDefaults.standardUserDefaults setValue:list forKey:@"officialList"];
                for (HJChatSessionModel *sessionModel in sessionModels) {
                    if (![HJIM.shareIM.conversationManager isNewConversationBySessionId:sessionModel.sessionId]) {
                        [sessionModel bg_saveOrUpdate];
                    }
                }
            });
        } failure:^(NSError * _Nonnull error) {
            
        }];
    }
    
}

- (void)loadOfficialAccountCompletion:(void (^__nullable)(NSArray  * _Nullable datas))completion {
    
    NSArray *list = [NSUserDefaults.standardUserDefaults valueForKey:@"officialList"];
    NSMutableArray *sessionModels = [self transitionToSessionModels:list];
    if (completion) {
        completion(sessionModels);
    }
    
    [HJNetworking.shareNetwork GET:API_officialList parameters:nil success:^(NSDictionary * _Nonnull responseObject, id  _Nonnull data) {
        
        NSArray *list = data[@"list"];
        NSMutableArray *sessionModels = [self transitionToSessionModels:list];
        if (completion) {
            completion(sessionModels);
        }
        
        dispatch_async_sql_queue(^{
            [NSUserDefaults.standardUserDefaults setValue:list forKey:@"officialList"];
            for (HJChatSessionModel *sessionModel in sessionModels) {
                if (![HJIM.shareIM.conversationManager isNewConversationBySessionId:sessionModel.sessionId]) {
                    [sessionModel bg_saveOrUpdate];
                }
            }
        });
    } failure:^(NSError * _Nonnull error) {
        
    }];
    
}

- (NSMutableArray *)transitionToSessionModels:(NSArray *)datas {
    
    NSMutableArray *sessionModels = [NSMutableArray array];
    for (NSDictionary *dict in datas) {
        NSInteger Id = [dict[@"id"] integerValue];
        HJChatSessionModel *sessionModel = [[HJChatSessionModel alloc] init];
        sessionModel.chatType = HJChatTypeOfficial;
        if (Id == KaiPaySessionId) {
            sessionModel.officialType = HJChatOfficialTypeKaiPay;
        } else if (Id == KaiNewsSessionId) {
            sessionModel.officialType = HJChatOfficialTypeKaiNews;
        } else if (Id == KaiSupportSessionId) {
            sessionModel.officialType = HJChatOfficialTypeKaiSupport;
        }
        sessionModel.sessionId = getOfficiaSessionId(dict[@"id"]);
        sessionModel.isTop = toString(dict[@"isTop"]);
        sessionModel.isMute = toString(dict[@"is_mute"]);
        sessionModel.sessionName = dict[@"name"];
        sessionModel.sessionAvatar = dict[@"img"];
        [sessionModels addObject:sessionModel];
    }
    return sessionModels;
}

- (void)setBadgeNumber:(NSInteger)number completion:(void (^__nullable)(NSError  * _Nullable error))completion {
    [HJNetworking.shareNetwork POSTBodyJSON:API_setBadgeCount parameters:@{
        @"badgeCount": @(number)
    } success:^(NSDictionary * _Nonnull responseObject, id  _Nonnull data) {
        !completion ?: completion(nil);
    } failure:^(NSError * _Nonnull error) {
        !completion ?: completion(error);
    }];
    
}

@end
